package com.example.kafka.service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Random;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.example.kafka.entity.Account;
import com.example.kafka.entity.User;
import com.example.kafka.repository.AccountRepository;
import com.example.kafka.repository.UserRepository;

import lombok.extern.slf4j.Slf4j;

/**
 * 没有数据不一致风险的服务示例
 * 正确使用事务管理，确保数据一致性
 */
@Slf4j
@Service
public class TransactionSafeService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private AccountRepository accountRepository;

    /**
     * 安全示例1：用户注册时创建用户和账户，使用事务保护
     * 如果任何步骤失败，整个操作会回滚，确保数据一致性
     */
    @Transactional(rollbackFor = Exception.class)
    public String createUserWithAccountSafe(String username, String email, String fullName) {
        log.info("开始创建用户和账户（有事务保护）: {}", username);

        try {
            // 第一步：创建用户
            User user = new User();
            user.setUsername(username);
            user.setEmail(email);
            user.setFullName(fullName);
            user.setBalance(BigDecimal.ZERO);
            user.setStatus("ACTIVE");
            user = userRepository.save(user);
            log.info("用户创建成功: {}", user.getId());

            // 模拟可能的异常情况
            if (shouldSimulateFailure()) {
                throw new RuntimeException("模拟创建账户时发生异常");
            }

            // 第二步：创建账户
            Account account = new Account();
            account.setUserId(user.getId());
            account.setAccountNumber(generateAccountNumber());
            account.setBalance(BigDecimal.ZERO);
            account.setAccountType("SAVINGS");
            account.setStatus("ACTIVE");
            account = accountRepository.save(account);
            log.info("账户创建成功: {}", account.getId());

            return "用户和账户创建成功";
        } catch (Exception e) {
            log.error("创建用户和账户失败，事务将回滚: {}", e.getMessage());
            // 事务会自动回滚，确保数据一致性
            throw e;
        }
    }

    /**
     * 安全示例2：转账操作使用事务保护
     * 如果任何步骤失败，整个操作会回滚，确保资金安全
     */
    @Transactional(rollbackFor = Exception.class)
    public String transferMoneySafe(Long fromUserId, Long toUserId, BigDecimal amount) {
        log.info("开始转账操作（有事务保护）: 从用户{}转账{}到用户{}", fromUserId, amount, toUserId);

        try {
            // 第一步：从源用户扣款
            User fromUser = userRepository.findById(fromUserId).orElse(null);
            if (fromUser == null) {
                throw new RuntimeException("源用户不存在");
            }
            if (fromUser.getBalance().compareTo(amount) < 0) {
                throw new RuntimeException("余额不足");
            }

            fromUser.setBalance(fromUser.getBalance().subtract(amount));
            userRepository.save(fromUser);
            log.info("从用户{}扣款成功，余额: {}", fromUserId, fromUser.getBalance());

            // 模拟可能的异常情况
            if (shouldSimulateFailure()) {
                throw new RuntimeException("模拟入账时发生异常");
            }

            // 第二步：向目标用户入账
            User toUser = userRepository.findById(toUserId).orElse(null);
            if (toUser == null) {
                throw new RuntimeException("目标用户不存在");
            }

            toUser.setBalance(toUser.getBalance().add(amount));
            userRepository.save(toUser);
            log.info("向用户{}入账成功，余额: {}", toUserId, toUser.getBalance());

            return "转账成功";
        } catch (Exception e) {
            log.error("转账操作失败，事务将回滚: {}", e.getMessage());
            // 事务会自动回滚，确保资金安全
            throw e;
        }
    }

    /**
     * 安全示例3：批量更新用户状态和账户状态，使用事务保护
     * 如果任何更新失败，整个操作会回滚，确保状态一致性
     */
    @Transactional(rollbackFor = Exception.class)
    public String batchUpdateUserStatusSafe(List<Long> userIds, String newStatus) {
        log.info("开始批量更新用户状态（有事务保护）: {} 个用户", userIds.size());

        try {
            for (Long userId : userIds) {
                // 更新用户状态
                User user = userRepository.findById(userId).orElse(null);
                if (user != null) {
                    user.setStatus(newStatus);
                    userRepository.save(user);
                    log.info("用户{}状态更新成功", userId);
                }

                // 模拟可能的异常情况
                if (shouldSimulateFailure()) {
                    throw new RuntimeException("模拟更新账户状态时发生异常");
                }

                // 更新该用户的所有账户状态
                List<Account> accounts = accountRepository.findByUserId(userId);
                for (Account account : accounts) {
                    account.setStatus(newStatus);
                    accountRepository.save(account);
                    log.info("账户{}状态更新成功", account.getId());
                }
            }

            return "批量更新完成，所有操作成功";
        } catch (Exception e) {
            log.error("批量更新失败，事务将回滚: {}", e.getMessage());
            // 事务会自动回滚，确保状态一致性
            throw e;
        }
    }

    /**
     * 安全示例4：复杂的业务操作，涉及多个表的更新，使用事务保护
     * 如果任何步骤失败，整个操作会回滚，确保数据一致性
     */
    @Transactional(rollbackFor = Exception.class)
    public String complexBusinessOperationSafe(Long userId, BigDecimal amount) {
        log.info("开始复杂业务操作（有事务保护）: 用户{}, 金额{}", userId, amount);

        try {
            // 步骤1：更新用户余额
            User user = userRepository.findById(userId).orElse(null);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }
            user.setBalance(user.getBalance().add(amount));
            userRepository.save(user);
            log.info("用户余额更新成功");

            // 模拟可能的异常情况
            if (shouldSimulateFailure()) {
                throw new RuntimeException("模拟更新账户时发生异常");
            }

            // 步骤2：更新用户的所有账户余额
            List<Account> accounts = accountRepository.findByUserId(userId);
            for (Account account : accounts) {
                account.setBalance(account.getBalance().add(amount));
                accountRepository.save(account);
                log.info("账户{}余额更新成功", account.getId());
            }

            // 模拟可能的异常情况
            if (shouldSimulateFailure()) {
                throw new RuntimeException("模拟更新用户状态时发生异常");
            }

            // 步骤3：更新用户状态
            user.setStatus("UPDATED");
            userRepository.save(user);
            log.info("用户状态更新成功");

            return "复杂业务操作完成";
        } catch (Exception e) {
            log.error("复杂业务操作失败，事务将回滚: {}", e.getMessage());
            // 事务会自动回滚，确保数据一致性
            throw e;
        }
    }

    /**
     * 安全示例5：使用编程式事务管理
     * 提供更细粒度的控制
     */
    @Transactional(rollbackFor = Exception.class)
    public String programmaticTransactionExample(Long userId, BigDecimal amount) {
        log.info("开始编程式事务示例: 用户{}, 金额{}", userId, amount);

        try {
            // 在同一个事务中执行多个操作
            User user = userRepository.findById(userId).orElse(null);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }

            // 操作1：更新用户余额
            user.setBalance(user.getBalance().add(amount));
            userRepository.save(user);
            log.info("用户余额更新成功");

            // 操作2：创建新的账户记录
            Account newAccount = new Account();
            newAccount.setUserId(userId);
            newAccount.setAccountNumber(generateAccountNumber());
            newAccount.setBalance(amount);
            newAccount.setAccountType("BONUS");
            newAccount.setStatus("ACTIVE");
            accountRepository.save(newAccount);
            log.info("新账户创建成功: {}", newAccount.getId());

            // 操作3：更新用户状态
            user.setStatus("BONUS_ADDED");
            userRepository.save(user);
            log.info("用户状态更新成功");

            return "编程式事务操作完成";
        } catch (Exception e) {
            log.error("编程式事务操作失败，事务将回滚: {}", e.getMessage());
            throw e;
        }
    }

    /**
     * 安全示例6：只读事务，提高性能
     */
    @Transactional(readOnly = true)
    public String readOnlyTransactionExample(Long userId) {
        log.info("开始只读事务示例: 用户{}", userId);

        try {
            User user = userRepository.findById(userId).orElse(null);
            if (user == null) {
                return "用户不存在";
            }

            List<Account> accounts = accountRepository.findByUserId(userId);

            StringBuilder result = new StringBuilder();
            result.append("用户信息: ").append(user.getUsername())
                    .append(", 余额: ").append(user.getBalance())
                    .append(", 状态: ").append(user.getStatus())
                    .append("\n");

            result.append("账户信息:\n");
            for (Account account : accounts) {
                result.append("- 账户号: ").append(account.getAccountNumber())
                        .append(", 余额: ").append(account.getBalance())
                        .append(", 类型: ").append(account.getAccountType())
                        .append(", 状态: ").append(account.getStatus())
                        .append("\n");
            }

            return result.toString();
        } catch (Exception e) {
            log.error("只读事务操作失败: {}", e.getMessage());
            throw e;
        }
    }

    private String generateAccountNumber() {
        return "ACC" + System.currentTimeMillis() + new Random().nextInt(1000);
    }

    private boolean shouldSimulateFailure() {
        // 30%的概率模拟失败
        return new Random().nextInt(100) < 30;
    }
}
